#!/usr/bin/python

# See documentatation at:
#    http://code.google.com/apis/documents/docs/3.0/developers_guide_python.html

import dateutil.parser
import datetime
import gdata.docs.data
import gdata.docs.client
import mimetypes
import os
import time

class Sync:
        def __init__(self, sync_root=None, source='gdata-sync-v1'):
                self._client = gdata.docs.client.DocsClient(source=source)
                self._client.ssl = True
                
                self._sync_root = None
                if not sync_root is None:
                        remote_folders = client.GetDocList(uri='/feeds/default/private/full/-/folder')
                        self._sync_root = self._subfolder(self._sync_root, remote_folders, sync_root)

        def Login(self, email, password):
                self._client.ClientLogin(email, password, client.source)

        def UseToken(self, token):
                self._client.auth_token = gdata.gauth.ClientLoginToken(token)

        def _modified_time(self, path):
                modified_time = os.path.getmtime(file_path)
                return datetime.datetime.fromtimestamp(modified_time)

        def _last_revision_time(self, entry):
                revisions = self._client.GetRevisions(entry.resource_id.text)
                last_revision = revisions.entry[0]
                return dateutil.parser.parse(last_revision.updated.text)

        def _subfolder(self, destination, current_folders, name):
                subfolder = None
                for folder in current_folders.entry:
                        if folder.title.text == name:
                                subfolder = folder
                                break
                if subfolder is None:
                        subfolder = self._client.Create(gdata.docs.data.FOLDER_LABEL, name, folder_or_id=destination)
                return subfolder

        def _copy_file_remote(self, path, destination):
                file = open(path)
                type, encoding = mimetypes.guess_type(path)
                if type is None:
                    type = 'application/octet-stream'
                size = os.path.getsize(path)
                source = gdata.data.MediaSource(file_handle=file, content_type=type, content_length=size)
                print 'Copy %s with type %s' % (path, type)
                # TODO: Use resumable uploads
                # TODO: File conversion
                location, filename = os.path.split(path)
                name, extension = os.path.splitext(filename)
                document = self._client.Upload(source, name, folder_or_uri=destination)

        def _copy_folder_remote(self, path, destination):
                if destination is None:
                        remote_folders = self._client.GetDocList(uri='/feeds/default/private/full/-/folder')
                else:
                        remote_folders = self._client.GetDocList(uri=destination.content.src + '/-/folder')
                for file in os.listdir(path):
                        new_path = os.path.join(path, file)
                        if os.path.isdir(new_path):
                                subfolder = self._subfolder(destination, remote_folders, file)
                                self._copy_folder_remote(new_path, subfolder)
                        else:
                                self._copy_file_remote(new_path, destination)

        def _copy_remote(self, path, destination_folders=[]):
                destination = self._sync_root
                for folder in destination_folders:
                    remote_folders = self._client.GetDocList(uri=destination.content.src + '/-/folder')
                    destination = self._subfolder(destination, remote_folders, folder)
                if os.path.isdir(path):
                        self._copy_folder_remote(path, self._sync_root)
                else:
                        self._copy_file_remote(path, self._sync_root)
                        
        def CopyRemote(self, path):
                self._copy_remote(path)
